// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose:  Implementation of CXFormsConfig class..
//   $Id$


// TODO: THE FOLLOWING ARE REQUIRED TO FINISH OFF THIS FUNCTIONALITY...
// ====================================================================
// 1. Resolve issues relating to hard-coded fp: namespace on this attribute.
// 2. Allow the @fp:config attribute to use both relative and full URLs.
// 3. Move all commonality between this class and fPCfgMgr to somewhere shared between projects
//    in Visual SourceSafe.

#include "stdafx.h"
#include "FP_ReturnCodes.h"
#include "XFormsConfig.h"

CXFormsConfig::CXFormsConfig()
:m_bShowFormBrand(false), m_bShowControlBrand(true), m_bDisplayDebugInfo(true), m_bShowMessageBrand(true), m_bShowSplashPage(true), m_bValidVersion(true), m_bValidDate(true), m_bShowSoftbar(false), m_bBrandSoftbar(true), m_bShowDefaultSubmitError(true), m_bInitialised(false)
{
	char buf[MAX_PATH + 1];
	DWORD dw = ::GetModuleFileName(_Module.m_hInst, buf, MAX_PATH);
	buf[dw] = '\0';

	CString sFilePath(buf);
	//should probably be URLEncode, but spaces should 
	//	be the only trouble in these paths
	sFilePath.Replace(" ", "%20");

	//Create a buffer to contain the res paths as they are formatted.
	int iLen = sFilePath.GetLength();
	char * strResPathRecipient = new char[iLen + 23]; //23 is the longest path length (longlogo);
	//create the first part of the string
	strcpy(strResPathRecipient,"res://");
	strcpy(&strResPathRecipient[6],sFilePath);
	
	//append the last part of the path for each one as we go.
	strcpy(&strResPathRecipient[6+iLen],"/little-fp.gif");
	m_bsControlBrandLogo = strResPathRecipient;

	strcpy(&strResPathRecipient[6+iLen],"/fp-longlogo.gif");
	m_bsMessageLogo = strResPathRecipient;

	strcpy(&strResPathRecipient[6+iLen],"/splash.htm");
	m_bsSplashPage = strResPathRecipient;
	delete [] strResPathRecipient;
}

CXFormsConfig::~CXFormsConfig()
{
}

// Populate the current object with data from the supplied XML DOM.
HRESULT CXFormsConfig::Initialise(IXMLDOMDocument *pConfigDOM)
{
	HRESULT hr = S_OK;
	if(pConfigDOM) {
		CComPtr<IXMLDOMElement> pDocEl;
		hr = pConfigDOM->get_documentElement(&pDocEl);
		if(hr == S_OK) {
			CComPtr<IXMLDOMNodeList> pNodeListHTML;
			pDocEl->getElementsByTagName(CComBSTR(L"html"), &pNodeListHTML);
			long lLength;
			pNodeListHTML->get_length(&lLength);
			for(int i = 0; i < lLength; i++) {
				CComPtr<IXMLDOMNode> pNodeHTML;
				pNodeListHTML->nextNode(&pNodeHTML);
				if(pNodeHTML) {
					CComQIPtr<IXMLDOMElement> pElHTML = pNodeHTML;
					if(pElHTML) {
						ProcessChildLinkElements(pElHTML);
						ProcessChildMetaElements(pElHTML);
					}
				}
			}
			m_bInitialised = true;
		}
	}
	return hr;
}

bool CXFormsConfig::FormBranding(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowFormBrand;
}

bool CXFormsConfig::ControlBranding(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowControlBrand;
}

BSTR CXFormsConfig::ControlBrandingLogo(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsControlBrandLogo.Copy();
}

bool CXFormsConfig::FormBrandingDebugInfo(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bDisplayDebugInfo;
}

bool CXFormsConfig::MessageBranding(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowMessageBrand;
}

BSTR CXFormsConfig::MessageLogo(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsMessageLogo.Copy();
}

bool CXFormsConfig::SplashPage(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowSplashPage;
}

BSTR CXFormsConfig::SplashPageURL(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsSplashPage.Copy();
}

BSTR CXFormsConfig::Version(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsVersion.Copy();
}

bool CXFormsConfig::ValidVersion(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bValidVersion;
}

BSTR CXFormsConfig::Date(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsDate.Copy();
}

bool CXFormsConfig::ValidDate(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bValidDate;
}

bool CXFormsConfig::Softbar(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowSoftbar;
}

BSTR CXFormsConfig::SoftbarName(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bsSoftbar.Copy();
}

bool CXFormsConfig::SoftbarBranding(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bBrandSoftbar;
}

bool CXFormsConfig::ShowDefaultSubmitError(void)
{
	if(!m_bInitialised)
		Initialise();
	return m_bShowDefaultSubmitError;
}

// Process settings from any <link> elements that are children of pParentElement.
HRESULT CXFormsConfig::ProcessChildLinkElements(IXMLDOMElement *pParentElement)
{
	HRESULT hr = S_OK;
	if(pParentElement) {
		CComPtr<IXMLDOMNodeList> pNodeListLink;
		pParentElement->getElementsByTagName(CComBSTR(L"link"), &pNodeListLink);
		long lLength = 0;
		pNodeListLink->get_length(&lLength);
		for(int i = 0; i < lLength; i++) {
			CComPtr<IXMLDOMNode> pNodeLink;
			pNodeListLink->nextNode(&pNodeLink);
			if(pNodeLink) {
				CComQIPtr<IXMLDOMElement> pElLink = pNodeLink;
				if(pElLink) {
					CComBSTR sRelValue;
					hr = GetAttribute(pElLink, CComBSTR(L"rel"), &sRelValue);
					if(SUCCEEDED(hr)) {
						sRelValue.ToLower();
						CComBSTR sHrefValue;
						hr = GetAttribute(pElLink, CComBSTR(L"href"), &sHrefValue);
						if(SUCCEEDED(hr)) {
							ExpandEnvironmentVariables(sHrefValue);
							hr = SetProperty(sRelValue, sHrefValue);
						}
					}
				}
			}
		}
	} else {
		hr = FP_E_BADARG;
		SetupErrorInfo(hr, L"CXFormsConfig::ProcessChildLinkElements");
	}
	return hr;
}

// Process settings from any <meta> elements that are children of pParentElement.
HRESULT CXFormsConfig::ProcessChildMetaElements(IXMLDOMElement *pParentElement)
{
	HRESULT hr = S_OK;
	if(pParentElement) {
		CComPtr<IXMLDOMNodeList> pNodeListMeta;
		pParentElement->getElementsByTagName(CComBSTR(L"meta"), &pNodeListMeta);
		long lLength = 0;
		pNodeListMeta->get_length(&lLength);
		for(int i = 0; i < lLength; i++) {
			CComPtr<IXMLDOMNode> pNodeMeta;
			pNodeListMeta->nextNode(&pNodeMeta);
			if(pNodeMeta) {
				CComQIPtr<IXMLDOMElement> pElMeta = pNodeMeta;
				if(pElMeta) {
					CComBSTR sNameValue;
					hr = GetAttribute(pElMeta, CComBSTR(L"name"), &sNameValue);
					if(SUCCEEDED(hr)) {
						sNameValue.ToLower();
						CComBSTR sContentValue;
						hr = GetAttribute(pElMeta, CComBSTR(L"content"), &sContentValue);
						if(SUCCEEDED(hr)) {
							sContentValue.ToLower();
							hr = SetProperty(sNameValue, sContentValue == L"false" ? false : true);
						}
					}
				}
			}
		}
	} else {
		hr = FP_E_BADARG;
		SetupErrorInfo(hr, L"CXFormsConfig::ProcessChildLinkElements");
	}
	return hr;
}

// Return the BSTR value of attribute sAttribute on XML element pElement.
HRESULT CXFormsConfig::GetAttribute(IXMLDOMElement *pElement, BSTR sAttribute, BSTR *psValue) const
{
	HRESULT hr = S_OK;
	if(pElement && sAttribute && psValue) {
		CComVariant vValue;
		hr = pElement->getAttribute(sAttribute, &vValue);
		if(hr == S_OK) {
			if(vValue.vt == VT_BSTR)
				*psValue = ::SysAllocString(vValue.bstrVal);
			else {
				hr = FP_E_BADARG;
				SetupErrorInfo(hr, L"CXFormsConfig::GetAttribute");
			}
		}
	} else {
		hr = FP_E_BADARG;
		SetupErrorInfo(hr, L"CXFormsConfig::GetAttribute");
	}
	return hr;
}

// Return sString with occurrences of {$xxx} replaced by expanded environment variable.
HRESULT CXFormsConfig::ExpandEnvironmentVariables(CComBSTR &sString) const
{
	HRESULT hr = S_FALSE;
	CStringW sBuf = sString;
	int i;
	while((i = sBuf.Find(L"{$")) != -1) {
		int i2 = i + 2;
		int i3 = sBuf.Find(L"}", i2);
		if(i3 != -1) {
			CStringW sTemp;
			wchar_t *lpwszEnv = _wgetenv(sBuf.Mid(i2, i3 - i2));
			if(lpwszEnv) {
				sTemp.Format(L"%s%s%s", sBuf.Left(i), lpwszEnv, sBuf.Mid(i3 + 1));
				sBuf = sTemp;
				hr = S_OK;
			} else {
				hr = E_INVALIDARG;
				break;
			}
		} else {
			hr = E_INVALIDARG;
			break;
		}
	}
	if(hr == S_OK)
		sString = sBuf.GetString();
	return hr;
}

// Set the specified property to the supplied BSTR value.
HRESULT CXFormsConfig::SetProperty(BSTR sProperty, BSTR sValue)
{
	HRESULT hr = S_OK;
	if(sProperty && sValue) {
		if(wcscmp(sProperty, L"controlbranding") == 0)
			m_bsControlBrandLogo = sValue;
		else if(wcscmp(sProperty, L"messagebranding") == 0)
			m_bsMessageLogo = sValue;
		else if(wcscmp(sProperty, L"splashpage") == 0)
			m_bsSplashPage = sValue;
		else if(wcscmp(sProperty, L"softbar") == 0)
			m_bsSoftbar = sValue;

		if(sValue == 0 || *sValue == L'\0')
			SetProperty(sProperty, false);
		else
			SetProperty(sProperty, true);
	} else {
		hr = FP_E_BADARG;
		SetupErrorInfo(hr, L"CXFormsConfig::SetProperty");
	}
	return hr;
}

// Set the specified property to the supplied boolean value.
HRESULT CXFormsConfig::SetProperty(BSTR sProperty, bool bValue)
{
	HRESULT hr = S_OK;
	if(sProperty) {
		if(wcscmp(sProperty, L"controlbranding") == 0)
			m_bShowControlBrand = bValue;
		else if(wcscmp(sProperty, L"messagebranding") == 0)
			m_bShowMessageBrand = bValue;
		else if(wcscmp(sProperty, L"formbranding") == 0)
			m_bShowFormBrand = bValue;
		else if(wcscmp(sProperty, L"controlstate") == 0)
			m_bDisplayDebugInfo = bValue;
		else if(wcscmp(sProperty, L"defaultsubmiterror") == 0)
			m_bShowDefaultSubmitError = bValue;
		else if(wcscmp(sProperty, L"splashpage") == 0)
			m_bShowSplashPage = bValue;
		else if(wcscmp(sProperty, L"softbar") == 0)
			m_bShowSoftbar = bValue;
	} else {
		hr = FP_E_BADARG;
		SetupErrorInfo(hr, L"CXFormsConfig::SetProperty");
	}
	return hr;
}

HRESULT CXFormsConfig::Initialise()
{
	m_bShowControlBrand = false;
	m_bShowMessageBrand = true;
	m_bShowFormBrand = false;
	m_bDisplayDebugInfo = false;
	m_bShowDefaultSubmitError = false;
	m_bShowSplashPage = false;
	m_bShowSoftbar = false;
	return S_OK;
}